package edu.alaska.gina.feeder.gina_puffinfeeder_android_viewer;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.Toast;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.Period;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.PeriodFormatter;
import org.joda.time.format.PeriodFormatterBuilder;
import java.util.ArrayList;
import java.util.Locale;
/**
* Activity that displays a full image while allowing navigation via 2 buttons across the bottom.
* Created by bobby on 7/1/13.
*/
public class ImageViewFrameActivty extends Activity implements View.OnClickListener {
private ArrayList<String[]> urls = new ArrayList<String[]>();
private ArrayList<String> titles = new ArrayList<String>();
private ArrayList<DateTime> times = new ArrayList<DateTime>();
private String feed;
private String description;
private String infoUrl;
private int position;
private Button newer;
private Button older;
/** Overridden Methods */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_PROGRESS);
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
setContentView(R.layout.activity_image_view_frame);
if (getActionBar() != null) {
getActionBar().setDisplayHomeAsUpEnabled(true);
getActionBar().setHomeButtonEnabled(true);
}
Bundle args = getIntent().getExtras();
urls = build3SizeArrayStructure(decodeUrlBundle(args, "url"));
titles = decodeBundle(args, "title");
times = parseTimeStrings_ISO8601(decodeBundle(args, "time"));
position = args.getInt("position");
feed = args.getString("feed_name");
description = args.getString("description");
infoUrl = args.getString("info");
newer = (Button) findViewById(R.id.navigation_newer);
older = (Button) findViewById(R.id.navigation_older);
newer.setOnClickListener(this);
older.setOnClickListener(this);
newImage(position);
endOfLine();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.viewer, menu);
return true;
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.navigation_newer:
if (position > 0)
newImage(position - 1);
break;
case R.id.navigation_older:
if (position < urls.size() - 1)
newImage(position + 1);
break;
}
endOfLine();
}
/*
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
finish();
return true;
case R.id.action_open_preferences:
this.startActivity(new Intent(this, PreferencesActivity.class));
return true;
case R.id.action_display_short_description:
DateTime t;
if (feed.equals("Barrow Radar") || feed.equals("Barrow Radar GeoTIF") || feed.equals("Barrow Webcam"))
t = times.get(position).withZone(DateTimeZone.forID("America/Anchorage"));
else
t = times.get(position).withZone(DateTimeZone.forID("UTC"));
Bundle x = new Bundle();
x.putString("description", buildDescription(t));
x.putString("title", titles.get(position));
ShortDescriptionFragment dFrag = new ShortDescriptionFragment();
dFrag.setArguments(x);
dFrag.show(getFragmentManager(), "description_dialog");
return true;
case R.id.action_display_short_feed_description:
Bundle info = new Bundle();
info.putString("description", description);
info.putString("title", feed);
info.putString("url", infoUrl);
ShortDescriptionFragment dFrag2 = new ShortDescriptionFragment();
dFrag2.setArguments(info);
dFrag2.show(getFragmentManager(), "description_dialog");
return true;
}
return super.onOptionsItemSelected(item);
}
*/
@Override
public void onBackPressed() {
finish();
super.onBackPressed();
}
/**
* Loads a new image into the main fragment.
* @param newPos Index number of image to be loaded.
*/
void newImage(int newPos) {
ImageViewerFragment iFrag = new ImageViewerFragment();
Bundle info = new Bundle();
info.putString("image_url_small", urls.get(newPos)[0]);
info.putString("image_url_med", urls.get(newPos)[1]);
info.putString("image_url_large", urls.get(newPos)[2]);
info.putString("bar_title", feed + " - " + titles.get(newPos));
if (feed.equals("Barrow Webcam"))
info.putString("bg_color", "#FFFFFF");
else
info.putString("bg_color", "#000000");
iFrag.setArguments(info);
Toast t = new Toast(this);
t.setText(findTimeDifference(times.get(newPos)));
t.show();
getFragmentManager().beginTransaction().replace(R.id.image_content_frame, iFrag).commit();
position = newPos;
}
/**
* Parses an ArrayList of Strings formatted in the ISO 8601 format into an ArrayList
* of DateTime objects.
* @param s ArrayList of Strings with Date/Time data formatted according to ISO 8601 standards.
* @return ArrayList of DateTime objects.
*/
ArrayList<DateTime> parseTimeStrings_ISO8601(ArrayList<String> s) {
ArrayList<DateTime> d = new ArrayList<DateTime>();
DateTimeFormatter formatter = DateTimeFormat.forPattern(getString(R.string.ISO8601_pattern));
for (String t : s)
d.add(formatter.parseDateTime(t));
return d;
}
/**
* Takes a bundle with Strings in it and spits out an ArrayList of those Strings.
* @param encoded Unprocessed bundle.
* @param key String used as an identifier during the encoding process.
* @return ArrayList of Strings.
*/
ArrayList<String> decodeBundle(Bundle encoded, String key) {
ArrayList<String> decoded = new ArrayList<String>();
for (int i = 0; encoded.getString("image_" + key + "_" + i) != null; i++)
decoded.add(encoded.getString("image_" + key + "_" + i));
return decoded;
}
/**
* Takes a bundle with Strings in it and spits out an ArrayList of those Strings.
* Extra modifications needed to decode the URL size arrays.
* @param encoded Unprocessed bundle.
* @param key String used as an identifier during the encoding process.
* @return ArrayList of Strings.
*/
ArrayList<String> decodeUrlBundle(Bundle encoded, String key) {
ArrayList<String> decoded = new ArrayList<String>();
int numSizes = encoded.getInt("num_image_sizes");
for (int i = 0; encoded.getString("image_" + key + "_" + i + "_0") != null; i++) {
for (int j = 0; j < numSizes; j++)
decoded.add(encoded.getString("image_" + key + "_" + i + "_" + j));
}
return decoded;
}
/**
* Takes a regular ArrayList of strings and converts it into an ArrayList<String[]>,
* each String[] having a length of 3.
* @param unstructured ArrayList of Strings.
* @return ArrayList of String[]s with length 3.
*/
ArrayList<String[]> build3SizeArrayStructure(ArrayList<String> unstructured) {
ArrayList<String[]> export = new ArrayList<String[]>();
for (int i = 0; i < unstructured.size(); i += 3)
export.add(new String[]{unstructured.get(i), unstructured.get(i + 1), unstructured.get(i + 2)});
return export;
}
/**
* Shows and hides UI buttons when necessary.
*/
void endOfLine() {
if (position <= 0) {
newer.setVisibility(View.GONE);
newer.setClickable(false);
older.setClickable(true);
older.setVisibility(View.VISIBLE);
}
else if (position >= urls.size() - 1) {
newer.setVisibility(View.VISIBLE);
newer.setClickable(true);
older.setClickable(false);
older.setVisibility(View.GONE);
}
else {
newer.setVisibility(View.VISIBLE);
newer.setClickable(true);
older.setClickable(true);
older.setVisibility(View.VISIBLE);
}
}
/**
* Builds the image description String.
* @param timeDate Time and Date stamp from the image.
* @return Image description String.
*/
String buildDescription(DateTime timeDate) {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
StringBuilder sb = new StringBuilder();
StringBuilder temp = new StringBuilder();
sb.append("Processed ").append(findTimeDifference(timeDate)).append("\n\n");
sb.append("Size: ");
String size = pickLoadSize(preferences);
if (size.equals("small"))
sb.append("Small (500 x 500).\n");
else if (size.equals("med"))
sb.append("Normal (1000 x 1000).\n");
else if (size.equals("large"))
sb.append("Large (2000 x 2000). \n");
sb.append("Date: ");
sb.append(timeDate.monthOfYear().getAsText(Locale.getDefault())).append(" ");
sb.append(timeDate.dayOfMonth().getAsText(Locale.getDefault())).append(", ");
sb.append(timeDate.yearOfEra().getAsText(Locale.getDefault())).append("\n");
sb.append("Time: ");
temp.append(timeDate.hourOfDay().getAsText(Locale.getDefault()));
if (temp.length() < 2) {
while (temp.length() < 2)
temp.insert(0, "0");
}
sb.append(temp);
sb.append(":");
temp = new StringBuilder();
temp.append(timeDate.minuteOfHour().getAsText(Locale.getDefault()));
if (temp.length() < 2) {
while (temp.length() < 2)
temp.insert(0, "0");
}
sb.append(temp).append(" ");
sb.append(timeDate.getZone().toTimeZone().getDisplayName());
return sb.toString();
}
/**
* Calculates how long it has been since the time stored in the parameters.
* @param pic Date and time to compare with.
* @return String describing how long it has been since the time described in the parameters.
*/
private String findTimeDifference(DateTime pic) {
DateTime now = new DateTime(System.currentTimeMillis());
Period diff = new Period(pic, now);
PeriodFormatter toastFormatter = new PeriodFormatterBuilder().
appendYears().appendSuffix(" year, ", " years, ").
appendMonths().appendSuffix(" month, ", " months, ").
appendWeeks().appendSuffix(" week, ", " weeks, ").
appendDays().appendSuffix(" day,", " days,").
appendSeparator(" and ").printZeroAlways().
appendHours().appendSuffix(" hour", " hours").appendLiteral(" ago.").toFormatter();
return toastFormatter.print(diff);
}
/** Methods used to choose size. */
/**
* Determines what sized image to load in the viewer.
* @return URL of image to be loaded.
*/
private String pickLoadSize(SharedPreferences sharedPreferences) {
ConnectivityManager connectivityManager = getConnectivityManager();
NetworkInfo nf = connectivityManager.getActiveNetworkInfo();
if (nf != null) {
if (isMetered(nf))
return sharedPreferences.getString("pref_smart_sizing_size", "small");
else
return sharedPreferences.getString("pref_viewer_image_size", "med");
}
else {
Log.d(getString(R.string.app_tag), "NetworkInfo null!");
return sharedPreferences.getString("pref_viewer_image_size", "med");
}
}
/**
* Grabs the ConnectivityManager object representing the device's networks.
* @return ConnectivityManager of the device.
*/
private ConnectivityManager getConnectivityManager() {
return (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
}
/**
* Determines if the network being used is a mobile network.
* @param net1 The NetworkInfo object representing the network to be tested.
* @return "true" if network is mobile (3/4G). "false" if it is not (wifi).
*/
private boolean isMetered(NetworkInfo net1) {
int type = net1.getType();
switch (type) {
case ConnectivityManager.TYPE_MOBILE:
case ConnectivityManager.TYPE_MOBILE_DUN:
case ConnectivityManager.TYPE_MOBILE_HIPRI:
case ConnectivityManager.TYPE_MOBILE_MMS:
case ConnectivityManager.TYPE_MOBILE_SUPL:
return true;
default:
return false;
}
}
}